import _ from 'lodash'
import {ToolboxDefine, VjsonComponent} from "./DefineVjsonComponent";
import {LayoutLoadHandler, LayoutOutLineDefineObject, LayoutSaveHandler, VjsonLayout} from "./DefineVjsonLayout";
import {Component, markRaw} from "vue";
import {addVJsonId} from "@/utils";

/**
 * 组件注册表
 */
const componentMap: { [k: string]: VjsonComponent<any, any, any> } = {}

/**
 * 布局注册表
 */
const layoutMap: { [k: string]: VjsonLayout } = {}


interface VariableDefine {
    /**
     * 变量名
     */
    name: String

    /**
     * 获取变量值
     */
    getValue(): any
}

/**
 * 全局表达式定义列表
 */
let _variableDefineList: VariableDefine[] = []

/**
 * 获取全部全局表达式定义
 */
export function getGlobalVariable(): VariableDefine[] {
    return _variableDefineList
}

/**
 * 根据名称获取全局表达式
 * @param name 名称，如果不传此参数，就返回全部全局定义
 */
export function getGlobalVariableByName(name): VariableDefine {
    return _.find(_variableDefineList, item => name === item.name)
}

/**
 * 设置全局变量环境
 * @param variableDefineList 变量定义
 */
export function setGlobalVariable(variableDefineList: VariableDefine[]) {
    _variableDefineList = variableDefineList
}

/**
 * 添加全局变量参数
 * @param variableDefine 变量定义
 */
export function addGlobalVariable(variableDefine: VariableDefine) {
    _variableDefineList.push(variableDefine)
}

/**
 * 注册组件
 */
export function registeVjsonComponent<P, E, M>(cmp: VjsonComponent<P, E, M>) {
    componentMap[cmp.cmpTag] = cmp;
}

/**
 * 注册布局
 */
export function registeVjsonLayout(layout: VjsonLayout) {
    layoutMap[layout.layoutTag] = layout
}

/**
 * 根据 cmpTag 获取组件注册数据
 */
export function getCmp(cmpTag: string): VjsonComponent<any, any, any> | undefined {
    return componentMap[cmpTag];
}

/**
 * 根据 cmpTag 获取设计时组件
 */
export function getDesignCmp(cmpTag: string): any {
    return this.getCmp(cmpTag)?.option.designer
}

/**
 * 根据 cmpTag 获取运行时组件
 */
export function getRuntimeCmp(cmpTag: string): any {
    return getCmp(cmpTag)?.option.runtime
}


/**
 * 获取布局读取文件的方法
 */
export function getLayoutLoadHandler(vjson: any): LayoutLoadHandler | undefined {
    const layoutName = vjson.layout
    return getLayout(layoutName)?.options.loadHandler
}

/**
 * 获取布局的大纲定义
 */
export function getLayoutOutline(vjson: any): LayoutOutLineDefineObject | undefined {
    const layoutName = vjson.layout
    return getLayout(layoutName)?.options.outline
}

/**
 * 获取布局保存文件的方法
 */
export function getLayoutSaveHandler(vjson: any): LayoutSaveHandler | undefined {
    const layoutName = vjson.layout
    return getLayout(layoutName)?.options.saveHandler
}

/**
 * 根据布局标签，获取布局定义
 */
export function getLayout(layoutTag: string): VjsonLayout | undefined {
    const ret = layoutMap[layoutTag];
    return ret
}

/**
 * 根据布局标签，获取布局组件
 */
export function getLayoutCmp(layoutTag: string): any {
    return getLayout(layoutTag)?.options.runtime
}

/**
 * 获取布局列表
 */
export function getLayoutList(): VjsonLayout[] {
    const list: VjsonLayout[] = []
    _.forOwn(layoutMap, (v, k) => {
        list.push(v)
    })
    return list
}

/**
 * 获取工具箱
 */
export function getToolbox(type: 'PC' | 'Mobile' = 'PC'): ToolboxDefine[] {
    const list: ToolboxDefine[] = []
    _.forOwn(componentMap, (cmp, cmpTag) => {
        list.push(...cmp.option.Toolbox)
    })
    return list
}

/**
 * 从工具箱拖拽组件时，生成组件代码
 */
export function toolboxCmpOnCreate(toolbox: ToolboxDefine): (from: string) => string {
    if (typeof toolbox.onCreate === 'function') {
        return toolbox.onCreate
    }

    if (!toolbox._cmpTag) {
        throw new Error('工具箱中的组件没有指定 cmpTag')
    }

    const cmp = getCmp(toolbox._cmpTag)

    return (from: string) => {
        const vjson = _.defaults({
            cmpTag: toolbox._cmpTag,

        }, cmp.option.defaults)

        return addVJsonId(vjson)
    }
}